package com.amumu.drama.common.utils;

import com.amumu.drama.common.modules.service.RedisService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Slf4j
@Component
public class LockHelper {

    /**
     * 锁前缀
     */
    private static final String LOCK_KEY_PRE = "LOCK_";
    private static final Integer DEFAULT_EXPIRE_SECONDS = 5;

    @Autowired
    private RedisService redisService;

    public boolean tryLock(String key, String value) {
        return tryLock(key, value, DEFAULT_EXPIRE_SECONDS);
    }

    /**
     * 尝试获取锁
     * @param key   key.
     * @param value value.
     * @return      lock success?
     */
    public boolean tryLock(String key, String value, int expireSeconds) {
        int retry = 5;
        String lockKey = LOCK_KEY_PRE + key;
        while (true) {
            if (tryIncrement(lockKey, value, expireSeconds)) {
                return true;
            }
            //按照重试配置来重试
            if (retry-- > 0){
                try {
                    Thread.sleep(10);
                } catch (InterruptedException e) {
                    log.error("重试等待错误：",e);
                    return false;
                }
            }else{
                return false;
            }
        }
    }

    /**
     * 释放锁
     * @param key   key.
     * @param value value.
     */
    public boolean unlock(String key, String value) {
        return unlock(key, value, DEFAULT_EXPIRE_SECONDS);
    }

    /**
     * 释放锁
     * @param key   key.
     * @param value value.
     * @param expireTime expireTime.
     */
    public boolean unlock(String key, String value, int expireTime) {
        String lockKey = LOCK_KEY_PRE + key;
        //先判断是不是当前的锁，如果是，才能释放
        if (tryIncrement(lockKey,value, expireTime)) {
            String lockValue = (String) redisService.get(lockKey);
            if (lockValue != null && lockValue.equals(value)) {
                redisService.del(lockKey);
            }
        }
        return false;
    }

    /**
     * 主要还是利用tair的version属性，来维持自增，自增成功则拿到锁，否则，等待
     */
    public boolean tryIncrement(String lockKey, String value, int expireSeconds) {
        String lockValue = (String) redisService.get(lockKey);
        if (lockValue == null) {
            redisService.set(lockKey, value, expireSeconds);
            return true;
        } else {
            return value.equals(lockValue);
        }
    }

}
